/*
 * Copyright (c) 2024 Black Sesame Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef _DAL_DOMAIN_PARTICIPANT_H_
#define _DAL_DOMAIN_PARTICIPANT_H_

#ifdef __cplusplus
extern "C" {
#endif

#include "dal/base_type.h"
#include "dal/ret_type.h"
#include "dal/status.h"
#include "dal/instance_handle.h"
#include "dal/string_sequence.h"
#include "dal/participant_monitor.h"
#include "dal/dds_entity.h"

#define DAL_DOMAIN_ID_MAX 160

#ifndef _DAL_BASE_TYPE_
typedef struct dal_time_s dal_time_t;
typedef struct dal_duration_s dal_duration_t;
#endif

#ifndef _DAL_CONDITION_H_
typedef struct dal_status_condition_s dal_status_condition_t;
#endif

typedef struct dal_domain_participant_s
{
    void* handle_;
} dal_domain_participant_t;

// User must init callbacks' memory to 0 before using.
typedef struct dal_domain_participant_listener_callbacks_s
{
    void (*on_inconsistent_topic)(dal_topic_t*, dal_inconsistent_topic_status_t*, void*);
    void (*on_liveliness_lost)(dal_datawriter_t*, dal_liveliness_lost_status_t*, void*);
    void (*on_offered_deadline_missed)(dal_datawriter_t*,
                                       dal_offered_deadline_missed_status_t*,
                                       void*);
    void (*on_offered_incompatible_qos)(dal_datawriter_t*,
                                        dal_offered_incompatible_qos_status_t*,
                                        void*);
    void (*on_data_on_readers)(dal_subscriber_t*, void*);
    void (*on_sample_lost)(dal_datareader_t*, dal_sample_lost_status_t*, void*);
    void (*on_data_available)(dal_datareader_t*, void*);
    void (*on_sample_rejected)(dal_datareader_t*, dal_sample_rejected_status_t*, void*);
    void (*on_liveliness_changed)(dal_datareader_t*, dal_liveliness_changed_status_t*, void*);
    void (*on_requested_deadline_missed)(dal_datareader_t*,
                                         dal_requested_deadline_missed_status_t*,
                                         void*);
    void (*on_requested_incompatible_qos)(dal_datareader_t*,
                                          dal_requested_incompatible_qos_status_t*,
                                          void*);
    void (*on_publication_matched)(dal_datawriter_t*, dal_publication_matched_status_t*, void*);
    void (*on_subscription_matched)(dal_datareader_t*, dal_subscription_matched_status_t*, void*);

    // offer callbacks the ability to access external resources, like binding
    // parameters;
    void* data_;
} dal_domain_participant_listener_callbacks_t;

typedef struct dal_domain_participant_listener_s
{
    void* handle_;
} dal_domain_participant_listener_t;

dal_domain_participant_listener_t*
dal_create_domain_participant_listener(dal_domain_participant_listener_callbacks_t callbacks);
dal_ret_t dal_delete_domain_participant_listener(dal_domain_participant_listener_t* listener);

dal_ret_t dal_domain_participant_enable(dal_domain_participant_t* entity);

dal_status_condition_t*
dal_domain_participant_get_statuscondition(dal_domain_participant_t* entity);

dal_status_mask_t dal_domain_participant_get_status_changes(dal_domain_participant_t* entity);

dal_instance_handle_t dal_domain_participant_get_instance_handle(dal_domain_participant_t* entity);

dal_publisher_t* dal_domain_participant_create_publisher(dal_domain_participant_t* participant,
                                                         dal_publisher_qos_t* qos,
                                                         dal_publisher_listener_t* listener,
                                                         dal_status_mask_t mask);

dal_publisher_t*
dal_domain_participant_create_publisher_with_profile(dal_domain_participant_t* participant,
                                                     dal_publisher_qos_t* qos,
                                                     const char* profile_name,
                                                     dal_publisher_listener_t* listener,
                                                     dal_status_mask_t mask);

dal_ret_t dal_domain_participant_delete_publisher(dal_domain_participant_t* participant,
                                                  dal_publisher_t* pub);

dal_subscriber_t* dal_domain_participant_create_subscriber(dal_domain_participant_t* participant,
                                                           dal_subscriber_qos_t* qos,
                                                           dal_subscriber_listener_t* sub_listener,
                                                           dal_status_mask_t mask);

dal_subscriber_t*
dal_domain_participant_create_subscriber_with_profile(dal_domain_participant_t* participant,
                                                      dal_subscriber_qos_t* qos,
                                                      const char* profile_name,
                                                      dal_subscriber_listener_t* sub_listener,
                                                      dal_status_mask_t mask);

dal_ret_t dal_domain_participant_delete_subscriber(dal_domain_participant_t* participant,
                                                   dal_subscriber_t* sub);

dal_subscriber_t* dal_domain_participant_get_builtin_subscriber(dal_domain_participant_t* part);

dal_topic_t* dal_domain_participant_create_topic(dal_domain_participant_t* participant,
                                                 const char* topic_name,
                                                 const char* type_name,
                                                 dal_topic_qos_t* qos,
                                                 dal_topic_listener_t* listener,
                                                 dal_status_mask_t mask);

dal_topic_t* dal_domain_participant_create_topic_with_profile(dal_domain_participant_t* participant,
                                                              const char* topic_name,
                                                              const char* type_name,
                                                              dal_topic_qos_t* qos,
                                                              const char* profile_name,
                                                              dal_topic_listener_t* listener,
                                                              dal_status_mask_t mask);

dal_ret_t dal_domain_participant_delete_topic(dal_domain_participant_t* participant,
                                              dal_topic_t* topic);

dal_topic_t* dal_domain_participant_find_topic(dal_domain_participant_t* participant,
                                               const char* topic_name,
                                               dal_duration_t* timeout);

dal_topic_description_t*
dal_domain_participant_lookup_topicdescription(dal_domain_participant_t* participant,
                                               const char* name);

dal_content_filtered_topic
dal_domain_participant_create_contentfilteredtopic(dal_domain_participant_t* participant,
                                                   const char* name,
                                                   dal_topic_t* related_topic,
                                                   const char* filter_expression,
                                                   dal_stringseq_t* expression_parameters);

dal_ret_t
dal_domain_participant_delete_contentfilteredtopic(dal_domain_participant_t* participant,
                                                   dal_content_filtered_topic contentfilteredtopic);

dal_multi_topic dal_domain_participant_create_multitopic(dal_domain_participant_t* participant,
                                                         const char* name,
                                                         const char* type_name,
                                                         const char* subscription_expression,
                                                         dal_stringseq_t* expression_parameters);

dal_ret_t dal_domain_participant_delete_multitopic(dal_domain_participant_t* participant,
                                                   dal_multi_topic multitopic);

dal_ret_t dal_domain_participant_delete_contained_entities(dal_domain_participant_t* part);

dal_ret_t dal_domain_participant_set_qos(dal_domain_participant_t* participant,
                                         dal_domain_participant_qos_t* qos);

dal_ret_t dal_domain_participant_get_qos(dal_domain_participant_qos_t* qos);

dal_ret_t dal_domain_participant_set_listener(dal_domain_participant_t* participant,
                                              dal_domain_participant_listener_t* listener,
                                              dal_status_mask_t mask);

dal_domain_participant_listener_t*
dal_domain_participant_get_listener(dal_domain_participant_t* part);

dal_ret_t dal_domain_participant_ignore_participant(dal_domain_participant_t* participant,
                                                    dal_instance_handle_t handle);

dal_ret_t dal_domain_participant_ignore_topic(dal_domain_participant_t* participant,
                                              dal_instance_handle_t handle);

dal_ret_t dal_domain_participant_ignore_publication(dal_domain_participant_t* participant,
                                                    dal_instance_handle_t handle);

dal_ret_t dal_domain_participant_ignore_subscription(dal_domain_participant_t* participant,
                                                     dal_instance_handle_t handle);

dal_domain_id dal_domain_participant_get_domain_id(dal_domain_participant_t* part);

dal_ret_t dal_domain_participant_assert_liveliness(dal_domain_participant_t* part);

dal_ret_t dal_domain_participant_set_default_publisher_qos(dal_domain_participant_t* participant,
                                                           dal_publisher_qos_t qos);

dal_ret_t dal_domain_participant_get_default_publisher_qos(dal_domain_participant_t* participant,
                                                           dal_publisher_qos_t* qos);

dal_ret_t dal_domain_participant_set_default_subscriber_qos(dal_domain_participant_t* participant,
                                                            dal_subscriber_qos_t qos);

dal_ret_t dal_domain_participant_get_default_subscriber_qos(dal_domain_participant_t* participant,
                                                            dal_subscriber_qos_t* qos);

dal_ret_t dal_domain_participant_set_default_topic_qos(dal_domain_participant_t* participant,
                                                       dal_topic_qos_t qos);

dal_ret_t dal_domain_participant_get_default_topic_qos(dal_domain_participant_t* participant,
                                                       dal_topic_qos_t* qos);

dal_ret_t dal_domain_participant_get_discovered_participants(dal_domain_participant_t* participant,
                                                             InstanceHandleSeq participant_handles);

dal_ret_t
dal_domain_participant_get_discovered_participant_data(dal_domain_participant_t* participant,
                                                       ParticipantBuiltinTopicData participant_data,
                                                       dal_instance_handle_t participant_handle);

dal_ret_t dal_domain_participant_get_discovered_topics(dal_domain_participant_t* participant,
                                                       InstanceHandleSeq topic_handles);

dal_ret_t dal_domain_participant_get_discovered_topic_data(dal_domain_participant_t* participant,
                                                           TopicBuiltinTopicData topic_data,
                                                           dal_instance_handle_t topic_handle);

BOOLEAN
dal_domain_participant_contains_entity(dal_domain_participant_t* participant,
                                       dal_instance_handle_t a_handle);

dal_ret_t dal_domain_participant_get_current_time(dal_domain_participant_t* participant,
                                                  dal_time_t* current_time);

dal_domain_participant_t* dal_create_domain_participant(dal_domain_id domain_id,
                                                        dal_domain_participant_qos_t* qos,
                                                        dal_domain_participant_listener_t* listener,
                                                        dal_status_mask_t mask);

dal_domain_participant_t*
dal_create_domain_participant_with_profile(dal_domain_id domain_id,
                                           dal_domain_participant_qos_t* qos,
                                           const char* profile_name,
                                           dal_domain_participant_listener_t* listener,
                                           dal_status_mask_t mask);

dal_ret_t dal_delete_domain_participant(dal_domain_participant_t* participant);

dal_guid_t dal_domain_participant_get_guid(dal_domain_participant_t* participant);

dal_ret_t dal_domain_participant_listener_set_participant_monitor_callback(
    dal_domain_participant_listener_t* listener,
    dal_participant_monitor_callback callback,
    void* callback_data);

dal_service_t* dal_domain_participant_create_service(
    dal_domain_participant_t* participant,
    const char* service_name,
    const char* request_reader_type_name,
    const char* response_writer_type_name,
    dal_datareader_qos_t* request_reader_qos,
    dal_datawriter_qos_t* response_writer_qos);

dal_service_t* dal_domain_participant_create_service_with_profile(
    dal_domain_participant_t* participant,
    const char* service_name,
    const char* request_reader_type_name,
    const char* response_writer_type_name,
    dal_datareader_qos_t* request_reader_qos,
    dal_datawriter_qos_t* response_writer_qos,
    const char* request_reader_profile_name,
    const char* response_writer_profile_name);

dal_ret_t dal_domain_participant_delete_service(dal_domain_participant_t* participant,
                                                dal_service_t* service);

dal_client_t* dal_domain_participant_create_client(
    dal_domain_participant_t* participant,
    const char* service_name,
    const char* request_writer_type_name,
    const char* response_reader_type_name,
    dal_datawriter_qos_t* request_writer_qos,
    dal_datareader_qos_t* response_reader_qos);

dal_client_t* dal_domain_participant_create_client_with_profile(
    dal_domain_participant_t* participant,
    const char* service_name,
    const char* request_writer_type_name,
    const char* response_reader_type_name,
    dal_datawriter_qos_t* request_writer_qos,
    dal_datareader_qos_t* response_reader_qos,
    const char* request_writer_profile_name,
    const char* response_reader_profile_name);

dal_ret_t dal_domain_participant_delete_client(dal_domain_participant_t* participant,
                                               dal_client_t* client);

#ifdef __cplusplus
}
#endif

#endif  // _DAL_DOMAIN_PARTICIPANT_H_
